//===============================================================================
// Microsoft patterns & practices
// Mobile Client Software Factory - July 2006
//===============================================================================
// Copyright  Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================

using System;
using System.Reflection;
using System.Globalization;

namespace Microsoft.Practices.Mobile.ObjectBuilder
{
	/// <summary>
	/// Strongly-typed object consumed by the <see cref="PropertySetterPolicy"/> to 
	/// set dependency values on properties.
	/// </summary>
	public class StrongTypedPropertySetterInfo : IPropertySetterInfo
	{
		/// <summary>
		/// Delegate that defines the method that is used to set the value 
		/// of a property.
		/// </summary>
		public delegate void SetValueHandler(object target, object value);

		Type propertyType;
		IParameter dependencyParameter;
		SetValueHandler setValue;

		/// <summary>
		/// Initializes the information object.
		/// </summary>
		public StrongTypedPropertySetterInfo(Type propertyType, IParameter dependencyParameter, SetValueHandler handler)
		{
			Guard.ArgumentNotNull(propertyType, "propertyType");
			Guard.ArgumentNotNull(dependencyParameter, "dependencyParameter");
			Guard.ArgumentNotNull(handler, "handler");

			this.propertyType = propertyType;
			this.dependencyParameter = dependencyParameter;
			this.setValue = handler;
		}

		/// <summary>
		/// Retrieves the property information object used to set the property value.
		/// </summary>
		public PropertyInfo SelectProperty(IBuilderContext context, Type type, string id)
		{
			return new StrongTypedPropertyInfo(propertyType, setValue);
		}

		/// <summary>
		/// Retrieves the value of the dependency parameter received in the constructor.
		/// </summary>
		public object GetValue(IBuilderContext context, Type type, string id, PropertyInfo propInfo)
		{
			return dependencyParameter.GetValue(context);
		}

		class StrongTypedPropertyInfo : PropertyInfo
		{
			Type propertyType;
			SetValueHandler setValue;

			public StrongTypedPropertyInfo(Type propertyType, SetValueHandler handler)
			{
				this.propertyType = propertyType;
				this.setValue = handler;
			}

			public override bool CanWrite
			{
				get { return true; }
			}

			public override Type PropertyType
			{
				get { return propertyType; }
			}

			public override void SetValue(object obj, object value, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture)
			{
				setValue(obj, value);
			}

			#region NotImplemented Members

			public override PropertyAttributes Attributes
			{
				get { throw new NotImplementedException(); }
			}

			public override bool CanRead
			{
				get { throw new NotImplementedException(); }
			}

			public override MethodInfo[] GetAccessors(bool nonPublic)
			{
				throw new NotImplementedException();
			}

			public override MethodInfo GetGetMethod(bool nonPublic)
			{
				throw new NotImplementedException();
			}

			public override ParameterInfo[] GetIndexParameters()
			{
				throw new NotImplementedException();
			}

			public override MethodInfo GetSetMethod(bool nonPublic)
			{
				throw new NotImplementedException();
			}

			public override object GetValue(object obj, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture)
			{
				throw new NotImplementedException();
			}

			public override Type DeclaringType
			{
				get { throw new NotImplementedException(); }
			}

			public override object[] GetCustomAttributes(Type attributeType, bool inherit)
			{
				throw new NotImplementedException();
			}

			public override object[] GetCustomAttributes(bool inherit)
			{
				throw new NotImplementedException();
			}

			public override bool IsDefined(Type attributeType, bool inherit)
			{
				throw new NotImplementedException();
			}

			public override string Name
			{
				get { throw new NotImplementedException(); }
			}

			public override Type ReflectedType
			{
				get { throw new NotImplementedException(); }
			}

			#endregion
		}
	}
}
